' *** FFT11.01 - Q (=2^N) POINT FFT (POSITIVE FREQUENCIES ONLY) ***

' ILLUSTRATES OVERSAMPLING - ALSO SEE FFT11.02

10 SCREEN 9, 1: COLOR 15, 1: CLS 'SETUP DISPLAY SCREEN

PRINT "THIS PROGRAM ILLUSTRATES 16:1 OVERSAMPLING.  BEST ILLUSTRATION IS"

PRINT "WITH N=5 (Q = 32) AND F=15.  GENERATE SINUSOID AND RECONSTRUCT TO SEE"

PRINT "THE INTERMODULATION DISTORTION.  GENERATE SINUSOID AGAIN (F = 15 AGAIN)"

PRINT "THEN SELECT THE 'OVERSAMPLE' OPTION FROM THE MAIN MENU.  RECONSTRUCT"

PRINT "THIS OVERSAMPLED WAVEFORM AND VIEW THE RESULTS."

PRINT

INPUT "ENTER TO CONTINUE"; A$



12 CLS : PRINT "INPUT NUMBER OF DATA POINTS AS 2^N. "

14 INPUT "N = "; N

16 Q = 2 ^ N: N1 = N - 1: Q1 = Q - 1: Q2 = Q / 2: Q3 = Q2 - 1: Q4 = Q / 4: Q5 = Q4 - 1

18 Q8 = Q / 8: Q9 = Q8 - 1: Q34 = Q2 + Q4: Q16 = Q / 16

20 DIM C(Q * 16), S(Q * 16), KC(Q2 * 16), KS(Q2 * 16)' DIM DATA AND TWIDDLE FACTORS

30 PI = 3.141592653589793#: P2 = 2 * PI: K1 = P2 / Q

   ' ***  GENERATE TWIDDLE FACTORS  ****

32 FOR I = 0 TO Q2: KC(I) = COS(K1 * I): KS(I) = SIN(K1 * I): NEXT

34 IOFLG = 2' SET OUTPUT TO GRAPHIC DISPLAY

36 '    ********   MAIN MENU   ********

40 CLS ' DISPLAY MAIN MENU

50 PRINT SPC(30); "MAIN MENU": PRINT : PRINT

60 PRINT SPC(5); "1 = ANALYZE COSINE FUNCTION": PRINT

62 PRINT SPC(5); "2 = INVERSE TRANSFORM": PRINT

64 PRINT SPC(5); "3 = SETUP DISPLAY": PRINT

65 PRINT SPC(5); "4 = OVERSAMPLE DATA": PRINT

66 PRINT SPC(5); "5 = EXIT": PRINT

70 PRINT SPC(10); "MAKE SELECTION :";

80 A$ = INKEY$: IF A$ = "" THEN 80

90 A = VAL(A$): ON A GOSUB 600, 200, 800, 700, 990

95 GOTO 40

   ' ********************************************

   ' ***  FFT05-02 *** POSITIVE FREQUENCY FFT ***

   ' ********************************************

98  '         *****************************

100 '         ***   FORWARD TRANSFORM   ***

102 '         *****************************

106 '          ***  TRANSFORM STAGE 1  ***

108 T9 = TIMER

110 C(0) = (S(0) + S(Q2)) / 2: C(1) = (S(0) - S(Q2)) / 2

112 FOR I = 1 TO Q3: I2 = 2 * I: INDX = 0

114 FOR J = 0 TO N1: IF I AND 2 ^ J THEN INDX = INDX + 2 ^ (N - 2 - J)

116 NEXT J

118 C(I2) = (S(INDX) + S(INDX + Q2)) / 2: C(I2 + 1) = (S(INDX) - S(INDX + Q2)) / 2

120 NEXT I

122 FOR I = 0 TO Q1: S(I) = 0: NEXT I

'       *********  REMAINING STAGES  **********

124 FOR M = 1 TO N1: QP = 2 ^ M: QPI = 2 ^ (N1 - M)

126  FOR K = 0 TO QPI - 1

128   FOR J = 0 TO QP / 2: J0 = J + (2 * K * QP): J1 = J0 + QP: K2 = QPI * J

130   JI = J1 - (2 * J)

132   CTEMP1 = C(J0) + C(J1) * KC(K2) - S(J1) * KS(K2)

134   STEMP1 = S(J0) + C(J1) * KS(K2) + S(J1) * KC(K2)

136   CTEMP2 = C(J0) - C(J1) * KC(K2) + S(J1) * KS(K2)

138   S(JI) = (C(J1) * KS(K2) + S(J1) * KC(K2) - S(J0)) / 2

140   C(J0) = CTEMP1 / 2: S(J0) = STEMP1 / 2: C(JI) = CTEMP2 / 2

142   NEXT J

144  NEXT K

146 NEXT M

148 FOR J = Q2 + 1 TO Q1: C(J) = 0: S(J) = 0: NEXT J

150 T9 = TIMER - T9: SK1 = 2

172 ON IOFLG GOSUB 300, 350

174 LOCATE 23, 20

176 PRINT : PRINT : INPUT "ENTER TO CONTINUE:"; A$

178 RETURN



REM ****************************************************

REM *              INVERSE TRANSFORM                   *

REM ****************************************************

200 PRINT : T9 = TIMER: SK1 = 1

202 FOR M = N1 TO 1 STEP -1' LOOP FOR STAGES OF COMPUTATION

204  QP2 = 2 ^ (M): QP = INT(QP2 / 2): QP4 = 2 * QP2: QPI = 2 ^ (N1 - M)

206  FOR I = 0 TO Q - (QP2) STEP QP4

208   FOR J = 0 TO QP: KI = J + I: KT = J * QPI: KJ = QP2 + KI

212    MCT = C(J + I) - C(I + QP2 - J): MST = S(J + I) + S(I + QP2 - J)

214    CTEMP = MCT * KC(KT) + MST * KS(KT)

216    STEMP = MST * KC(KT) - MCT * KS(KT)

218    CTEMP2 = (2 * C(J + I)) - CTEMP * KC(KT) + STEMP * KS(KT)

220    S(KI) = (2 * S(J + I)) - CTEMP * KS(KT) - STEMP * KC(KT)

222    C(KJ) = CTEMP: S(KJ) = STEMP: C(KI) = CTEMP2

224   NEXT J

226  NEXT I

228 NEXT M

229 '    ********  FINAL STAGE  ********

230 FOR I = 0 TO Q3: I2 = 2 * I: INDX = 0

232 FOR J = 0 TO N1: IF I AND 2 ^ J THEN INDX = INDX + 2 ^ (N - 2 - J)

234 NEXT J

236 S(INDX) = C(I2) + C(I2 + 1): S(INDX + Q2) = C(I2) - C(I2 + 1)

238 NEXT I

240 FOR I = 0 TO Q1: C(I) = 0: NEXT I

242 T9 = TIMER - T9

244 GOSUB 370 ' PLOT DATA

246 INPUT "ENTER TO CONTINUE"; A$

248 RETURN



REM *******************************************************

REM *               DATA OUTPUT ROUTINES                  *

REM *******************************************************

300 REM **** PRINT OUTPUT DATA ****

302 CLS : PRINT "FREQ     F(COS)       F(SIN)       "'PRINT HEADING

304 PRINT : PRINT

306 FOR Z = 0 TO Q4

308 GOSUB 320' PRINT DATA

310 LCTR = LCTR + 1: IF LCTR = 20 THEN LCTR = 0: INPUT A$

312 NEXT Z

314 PRINT : PRINT "TIME ="; T9

316 LCTR = 0

318 RETURN

320 PRINT USING "###_    "; Z; :

322 PRINT USING "+##.#####_    "; C(Z); S(Z);

324 PRINT USING "###_    "; Z + Q4; :

326 PRINT USING "+##.#####_    "; C(Z + Q4); S(Z + Q4)

330 RETURN



349 REM ******  PLOT DATA ******

350 CLS : X0 = 50: Y0 = 300: XSF = 500 / Q2: YSF = 300

352 LINE (X0 - 1, 50)-(X0 - 1, Y0)' DRAW Y AXIS

354 LINE (X0, Y0)-(X0 + 500, Y0)' DRAW X AXIS

356 LINE (X0, Y0)-(X0, Y0)' SET PEN TO ORIGIN

358 FOR I = 0 TO Q2

360 YP = SQR(C(I) ^ 2 + S(I) ^ 2)' FIND RSS OF DATA POINT

362 LINE (X0 + XSF * I, Y0 - YSF * YP)-(X0 + XSF * I, Y0 - YSF * YP)' DRAW POINT

364 NEXT I

366 RETURN

368 REM *****   PLOT RECONSTRUCTED DATA   *********

370 CLS : X0 = 50: Y0 = 170: XSF = 500 / Q: YSF = 100

372 LINE (X0 - 1, 50)-(X0 - 1, (2 * (Y0 - 50)) + 50)' DRAW Y AXIS

374 LINE (X0, Y0)-(X0 + 500, Y0)' DRAW X AXIS

376 LINE (X0, Y0)-(X0, Y0)' SET PEN TO ORIGIN

378 FOR I = 0 TO Q

380 YP = S(I)' GET DATA POINT

382 LINE (X0 + XSF * I, Y0 - YSF * YP)-(X0 + XSF * I, Y0 - YSF * YP)' DRAW POINT

384 NEXT I

386 RETURN



400 ' GENERATE SINUSOID

410 FOR I = 0 TO Q

416 C(I) = 0: S(I) = COS(F9 * K1 * I)

430 NEXT

440 RETURN



600 CLS : PRINT : PRINT : REM * GENERATE COSINE COMPONENT *

602 INPUT "PLEASE SPECIFY FREQUENCY "; F9

604 PRINT "PREPARING DATA INPUT - PLEASE WAIT!"

610 GOSUB 400 ' GENERATE COSINE WAVE

614 'PRINT : INPUT "DATA READY - ENTER TO CONTINUE"; A$

620 GOSUB 100 ' PERFORM PFFFT

630 RETURN



700 REM *** 8X OVERSAMPLE DATA ***

702 FOR I = Q2 TO Q ' CLEAR UPPER ARRAY

704 C(I) = 0: S(I) = 0

706 NEXT I

710 N = N + 4: N1 = N - 1' INCREASE 2^N EXPONENT

714 Q = 2 ^ N: Q1 = Q - 1' INCREASE Q & GEN NEW CONSTANTS

716 Q2 = Q / 2: Q3 = Q2 - 1: Q4 = Q / 4: Q5 = Q4 - 1: Q8 = Q / 8

718 K1 = P2 / Q

719 ' ***  GENERATE NEW TWIDDLE FACTORS  ****

720 FOR I = 0 TO Q2: KC(I) = COS(K1 * I): KS(I) = SIN(K1 * I): NEXT

722 GOSUB 350 ' PLOT OVERSAMPLED DATA

724 INPUT A$ ' WAIT USER - DATA IS NOW OVERSAMPLED

726 RETURN



800 REM ***  SETUP PRINTOUT/GRAPHIC DISPLAY  ***

802 CLS ' CLEAR SCREEN

804 INPUT "GRAPHIC DISPLAY (Y/N)"; A$

806 IF A$ = "Y" THEN IOFLG = 2 ELSE IOFLG = 1

808 RETURN



990 END: STOP



